package com.ys.data.async;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.common.annotation.ApiLogDetail;
import com.common.base.BaseEnum;
import com.common.pojo.Result;
import com.common.util.FastJsonUtils;
import com.common.util.RedisUtil;
import com.common.vo.*;
import com.ys.data.client.AuthClient;
import com.ys.data.client.CoreClient;
import com.ys.data.service.OrderService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.annotation.Transient;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import com.ys.data.entry.MakeAppInfo;
import com.ys.data.entry.Order;
import com.ys.data.service.MakeAppInfoService;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicReference;


/**
 * @version: V1.0
 * @author: szw
 * @className: AsyncService
 * @packageName: AsyncService
 * @description: 异步处理任务接口方便统一调用
 * @date: 2021-1-23
 **/
@Component
@Slf4j
public class AsyncService {

    @Resource
    private AuthClient authClient;

    @Resource
    private CoreClient coreClient;

    @Resource
    private RedisUtil redisUtil;

    @Resource
    private OrderService orderService;

    @Resource
    @Lazy
    private MakeAppInfoService makeAppInfoService;

    /**
     * 订单完成更新用户积分状态、订单次数
     * @param makeAppInfoVo
     * @param orderVo
     * @return
     */
    @Transient
    @Async("asyncServiceExecutor")
    @ApiLogDetail(detail = "订单服务-异步处理数据-订单完成更新用户积分状态、订单次数",operationType=BaseEnum.ASYNC)
    public Integer initRoleDataResult(MakeAppInfoVo makeAppInfoVo, OrderVo orderVo) throws Exception {
        log.info("->>>>>>开始异步更新用户积分信息!");
        if (Objects.isNull(makeAppInfoVo) || Objects.isNull(orderVo)) {
            log.error("->>>>>>同步失败！数据为空,请核对数据后重试！");
        }
        //查询用户所有已完成的订单
        QueryWrapper<Order> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", orderVo.getUserId()).and(wrapper ->
                wrapper.eq("order_status", BaseEnum.ORDER_STATUS_OK.getDesc()));
        List<Order> orderList = orderService.findUserOrders(queryWrapper);
        if (CollectionUtils.isEmpty(orderList)) {
            return 0;
        }
        //获取商品积分计算规则
        String key = BaseEnum.INIT_DICT_REDIS_KEY.getCode();
        String redisData = redisUtil.get(key);
        List<DictDataVo> redisRoleList = FastJsonUtils.getArrayJson(redisData, DictDataVo.class);
        if (CollectionUtils.isEmpty(redisRoleList)) {
            log.error("商品规格字典未同步到Redis中，请重试！");
            return 0;
        }
        //计算积分值
        AtomicReference<String> commodityValue = new AtomicReference<>("");
        redisRoleList.forEach(dict -> {
            if (StringUtils.equals(BaseEnum.DICT_COMMODITY_CLOTHES.getCode(), dict.getDictType())) {
                commodityValue.set(dict.getDictTypeValue());
            }
        });
        Integer integral = Integer.valueOf(commodityValue.get());
        //计算开始
        Integer commodityIntegral = calculation(orderList, integral);
        //加载排行榜数据
        loadUserRankingList(orderVo, orderList.size(), commodityIntegral);
        log.info("->>>>>>异步更新用户积分信息结束!");
        return 0;
    }

    /**
     * 计算用户积分
     *
     * @param orderList
     * @param commodityValue
     * @return
     */
    private Integer calculation(List<Order> orderList, Integer commodityValue) {
        try {
            AtomicReference<Integer> result = new AtomicReference<>(0);
            //计算开始
            orderList.forEach(order -> {
                //获取到预约的重量信息
                QueryWrapper<MakeAppInfo> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq("id", order.getMakeAppId()).and(
                        queryWrapper1 -> queryWrapper1.eq("make_app_status", BaseEnum.MAKE_STATUS_OK.getDesc()));
                List<MakeAppInfo> makeAppInfos = makeAppInfoService.findMakeAppInfos(queryWrapper);
                if (CollectionUtils.isEmpty(makeAppInfos)) {
                    log.error("未找到" + order.getUserId() + "该用户预约重量信息！");
                }
                makeAppInfos.forEach(item -> result.updateAndGet(v -> v + item.getMakeAppHeight()));
            });
            //计算
            result.updateAndGet(v -> v * commodityValue);
            return result.get();
        } catch (Exception e) {
            log.error("计算用户积分异常：" + e);
        }
        return 0;
    }

    /**
     * 加载用户排行榜数据
     *
     * @param orderVo
     * @param orderCount
     * @param integral   积分
     * @return
     */
    private void loadUserRankingList(OrderVo orderVo, Integer orderCount, Integer integral) {
        Result<?> result = coreClient.findUserRankingList(orderVo.getUserId());
        if (null == result.getData()) {
            RankingListVo rankingListVo = RankingListVo.builder()
                    .userId(orderVo.getUserId()).integralCount(Long.valueOf(integral))
                    .orderCount(Long.valueOf(orderCount)).created(BaseEnum.ADMIN.getCode())
                    .createdDate(LocalDateTime.now())
                    .build();
            coreClient.saveRankingList(rankingListVo);
        } else {
            RankingListVo rankingListVo = FastJsonUtils.getJson(FastJsonUtils.toJSONString(result.getData()),RankingListVo.class);
            rankingListVo.setIntegralCount(Long.valueOf(integral));
            rankingListVo.setOrderCount(Long.valueOf(orderCount));
            rankingListVo.setUpdate(BaseEnum.ADMIN.getCode());
            rankingListVo.setUpdateDate(LocalDateTime.now());
            coreClient.updateRankingList(rankingListVo);
        }
        //更新用户中心积分、订单数
        UserCodeVo userCodeVo = new UserCodeVo();
        userCodeVo.setUserId(orderVo.getUserId());
        Result<?> result1 = authClient.findUserCode(userCodeVo);
        UserCodeVo userCode1 = FastJsonUtils.getJson(FastJsonUtils.toJSONString(result1.getData()),UserCodeVo.class);
        if (Objects.isNull(userCode1)) {
            log.error("未查到用户中心数据！");
        }
        userCode1.setOrderCount(orderCount);
        userCode1.setPortrait(integral);
        userCode1.setUpdate(BaseEnum.ADMIN.getCode());
        userCode1.setUpdateDate(LocalDateTime.now());
        authClient.updateUserCode(userCode1);
    }
}
